package com.exmaple.lemlin.xmpp;

import android.app.Service;
import android.os.Vibrator;
import android.text.TextUtils;

import com.exmaple.lemlin.app.APPIM;
import com.exmaple.lemlin.app.Constants;
import com.exmaple.lemlin.entity.ChatMessage;
import com.exmaple.lemlin.entity.ChatRecord;
import com.exmaple.lemlin.entity.ChatRecordDao;
import com.exmaple.lemlin.entity.FriendGood;
import com.exmaple.lemlin.entity.FriendGoodDao;
import com.exmaple.lemlin.utils.ACache;
import com.exmaple.lemlin.utils.JsonUtils;
import com.exmaple.lemlin.utils.LogUtils;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.greendao.query.QueryBuilder;
import org.jivesoftware.smack.AbstractXMPPConnection;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.ConnectionListener;
import org.jivesoftware.smack.MessageListener;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.StanzaListener;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.chat2.Chat;
import org.jivesoftware.smack.chat2.ChatManager;
import org.jivesoftware.smack.chat2.IncomingChatMessageListener;
import org.jivesoftware.smack.chat2.OutgoingChatMessageListener;
import org.jivesoftware.smack.filter.AndFilter;
import org.jivesoftware.smack.filter.StanzaTypeFilter;
import org.jivesoftware.smack.packet.ExtensionElement;
import org.jivesoftware.smack.packet.Message;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.packet.Stanza;
import org.jivesoftware.smack.roster.PresenceEventListener;
import org.jivesoftware.smack.roster.Roster;
import org.jivesoftware.smack.roster.RosterEntry;
import org.jivesoftware.smack.roster.RosterGroup;
import org.jivesoftware.smack.roster.RosterListener;
import org.jivesoftware.smack.roster.SubscribeListener;
import org.jivesoftware.smack.roster.packet.RosterPacket;
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
import org.jivesoftware.smackx.iqregister.AccountManager;
import org.jivesoftware.smackx.muc.MultiUserChat;
import org.jivesoftware.smackx.muc.MultiUserChatException;
import org.jivesoftware.smackx.muc.MultiUserChatManager;
import org.jivesoftware.smackx.muc.RoomInfo;
import org.jivesoftware.smackx.muclight.MultiUserChatLight;
import org.jivesoftware.smackx.offline.OfflineMessageManager;
import org.jivesoftware.smackx.ping.PingFailedListener;
import org.jivesoftware.smackx.ping.PingManager;
import org.jivesoftware.smackx.search.ReportedData;
import org.jivesoftware.smackx.search.UserSearchManager;
import org.jivesoftware.smackx.vcardtemp.packet.VCard;
import org.jivesoftware.smackx.xdata.Form;
import org.jivesoftware.smackx.xdata.FormField;
import org.jxmpp.jid.BareJid;
import org.jxmpp.jid.DomainBareJid;
import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.EntityFullJid;
import org.jxmpp.jid.FullJid;
import org.jxmpp.jid.Jid;
import org.jxmpp.jid.impl.JidCreate;
import org.jxmpp.jid.parts.Localpart;
import org.jxmpp.jid.parts.Resourcepart;
import org.jxmpp.jid.util.JidUtil;
import org.jxmpp.stringprep.XmppStringprepException;

import java.io.IOException;
import java.net.InetAddress;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;

public class XmppConnection implements ConnectionListener, StanzaListener, IncomingChatMessageListener, OutgoingChatMessageListener, PingFailedListener {

    private final static String XMPP_SERVICE_DONAIN = "101.37.253.11";
    private final static String XMPP_SERVICE_HOST = "101.37.253.11";
    private final static int XMPP_SERVICE_PORT = 5222;

    private static volatile XmppConnection mXmppConnection = null;
    private AbstractXMPPConnection connection = null;

    //定时器
    private Timer mTimer;
    private final static int TIME_DELAY = 3000;

    public static XmppConnection getInstance() {
        if (mXmppConnection == null) synchronized (XmppConnection.class) {
            if (mXmppConnection == null)
                mXmppConnection = new XmppConnection();
        }
        return mXmppConnection;
    }

    public void openConnection() {
        if (connection != null) {
            return;
        }
        try {
            XMPPTCPConnectionConfiguration config = XMPPTCPConnectionConfiguration.builder()
                    //设置openfire服务器名称
                    .setXmppDomain(XMPP_SERVICE_DONAIN)
                    //设置openfire主机IP
                    .setHostAddress(InetAddress.getByName(XMPP_SERVICE_HOST))
                    //设置端口号：默认5222
                    .setPort(XMPP_SERVICE_PORT)
                    //设置离线状态
                    .setSendPresence(false)
                    //设置开启压缩，可以节省流量
                    .setCompressionEnabled(true)
                    //禁用SSL连接
                    .setSecurityMode(ConnectionConfiguration.SecurityMode.disabled)
                    .build();
            //初始化连接
            connection = new XMPPTCPConnection(config);
            //连接监听
            connection.addConnectionListener(this);
            //用户状态监听
            connection.addSyncStanzaListener((this), new AndFilter(new StanzaTypeFilter(Presence.class)));
        } catch (IOException e) {
            LogUtils.e("异常报告：" + e.getMessage());
        }
    }

    /**
     * 关闭连接
     */
    public void closeConnection() {
        if (connection == null) {
            return;
        }
        if (connection.isConnected()) {
            mTimer.cancel();
            connection.disconnect();
            connection = null;
        }
    }

    public void closeConnection1() {
        if (connection == null) {
            return;
        }
        if (connection.isConnected()) {
            connection.disconnect();
        }
    }

    /**
     * 判断连接是否通过了身份验证
     * 即是否已登录
     *
     * @return true/false
     */
    public boolean isAuthenticated() {
        return connection != null && connection.isConnected() && connection.isAuthenticated();
    }

    /**
     * 用户登录
     *
     * @param userName 用户名
     * @param password 用户密码
     */
    public boolean userLogin(String userName, String password) throws SmackException, IOException, XMPPException, InterruptedException {
        if (connection == null) {
            return false;
        }
        if (!connection.isConnected()) {
            connection.connect();
        }
        connection.login(userName, password);
        if (connection.isAuthenticated()) {

            //登录不同用户将删除上一个用户所有数据
            EntityFullJid fullJid = connection.getUser();
            APPIM.setLoginUser(fullJid);
            String current = fullJid.asBareJid().getLocalpartOrNull().intern();
            String before = ACache.get(APPIM.getContext()).getAsString(Constants.A_CACHE_USER_NAME);
            if (!TextUtils.isEmpty(before) && !current.equals(before)) {
                APPIM.getDaoSession().getFriendGoodDao().deleteAll();
                APPIM.getDaoSession().getChatRecordDao().deleteAll();
                APPIM.getDaoSession().getChatMessageDao().deleteAll();
            }
            ACache.get(APPIM.getContext()).put(Constants.A_CACHE_USER_NAME, userName);
            ACache.get(APPIM.getContext()).put(Constants.A_CACHE_USER_PWD, password);

            LogUtils.e("getFriendGoodDao:" + APPIM.getDaoSession().getFriendGoodDao().loadAll().size());

            //ping请求
            PingManager pingManager = PingManager.getInstanceFor(connection);
            pingManager.registerPingFailedListener(this);
            mTimer = new Timer();
            mTimer.schedule(new PingMyServerTimerTask(pingManager), TIME_DELAY, (30000));

            //获取离线消息
            OfflineMessageManager manager = new OfflineMessageManager(connection);
            for (Message message : manager.getMessages()) {
                if (message.getBody() != null) {
                    this.setMessage(message.getFrom().asEntityBareJidIfPossible(), message);
                }
            }
            manager.deleteMessages();

            //创建消息监听
            ChatManager chatManager = ChatManager.getInstanceFor(connection);
            chatManager.addOutgoingListener(this);
            chatManager.addIncomingListener(this);

            //需要经过同意才可以添加好友
            Roster.setDefaultSubscriptionMode(Roster.SubscriptionMode.manual);

            //设置在线
            Presence presence = new Presence(Presence.Type.available);
            presence.setMode(Presence.Mode.chat);
            connection.sendStanza(presence);
            return true;
        }
        return false;
    }

    /**
     * 用户注册
     *
     * @param userName 用户名
     * @param password 用户密码
     * @param map      用户属性
     */
    public boolean userLogon(String userName, String password, Map<String, String> map) throws
            IOException, InterruptedException, XMPPException, SmackException {
        if (connection == null) {
            return false;
        }
        if (!connection.isConnected()) {
            connection.connect();
        }
        AccountManager account = AccountManager.getInstance(connection);
        account.sensitiveOperationOverInsecureConnection((true));
        if (map == null) {
            map = new HashMap<>();
            map.put("name", userName);
            map.put("email", userName + "@example.com");
        }
        account.createAccount(Localpart.from(userName), password, map);
        return true;
    }

    /**
     * 用户注册
     *
     * @param userName 用户名
     * @param password 用户密码
     */
    public boolean userLogon(String userName, String password) throws
            IOException, InterruptedException, XMPPException, SmackException {
        return userLogon(userName, password, null);
    }

    /**
     * 获取所有好友信息
     *
     * @return List<RosterEntry>
     */
    public List<RosterEntry> getAllEntries() {
        if (connection == null)
            return null;
        return new ArrayList<>(Roster.getInstanceFor(connection).getEntries());
    }

    public void Test() {
        Set<RosterEntry> entries = Roster.getInstanceFor(connection).getEntries();
        LogUtils.e("--------" + entries.size());
        for (RosterEntry entry : entries) {
            LogUtils.e("--------" + entry.getName());
        }
        Roster.getInstanceFor(connection).createGroup("dddddd");

    }

    /**
     * 设置用户状态
     *
     * @param status 状态
     */
    public void setPresence(int status) {
        if (connection == null) {
            return;
        }
        Presence stanza = null;
        switch (status) {
            case 0://在线
                stanza = new Presence(Presence.Type.available);
                break;
            case 1://空闲
                stanza = new Presence(Presence.Type.available);
                stanza.setMode(Presence.Mode.chat);
                break;
            case 2://忙碌
                stanza = new Presence(Presence.Type.available);
                stanza.setMode(Presence.Mode.dnd);
                break;
            case 3://离开
                stanza = new Presence(Presence.Type.available);
                stanza.setMode(Presence.Mode.away);
                break;
            case 4://离线
                stanza = new Presence(Presence.Type.unavailable);
                break;
            default:
                break;
        }
        if (stanza != null) try {
            connection.sendStanza(stanza);
        } catch (SmackException.NotConnectedException | InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 创建聊天窗口
     *
     * @param toUserName 接收者用户名
     */
    public Chat createChatWindow(String toUserName) {
        if (TextUtils.isEmpty(toUserName))
            return null;
        toUserName = toUserName + "@" + connection.getXMPPServiceDomain().toString();
        try {
            return ChatManager.getInstanceFor(connection)
                    .chatWith(JidCreate.entityBareFrom(toUserName));
        } catch (XmppStringprepException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 发送消息
     *
     * @param chat 聊天窗口
     * @param msg  发送数据
     */
    public void sendChatMessage(Chat chat, String msg) {
        if (chat == null) {
            return;
        }
        try {
            Message message = new Message();
            message.setBody(msg);
            message.setType(Message.Type.chat);
            chat.send(message);
        } catch (SmackException.NotConnectedException | InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 发送消息
     *
     * @param toUserName 接收者用户名
     * @param msg        发送数据
     */
    public void sendChatMessage(String toUserName, String msg) {
        try {
            Chat chat = createChatWindow(toUserName);
            Message message = new Message();
            message.setBody(msg);
            message.setType(Message.Type.chat);
            chat.send(message);
        } catch (SmackException.NotConnectedException | InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 添加好友
     *
     * @param jidString 用户jid
     * @param again     命名
     */
    public boolean addCreateFriend(String jidString, String again, String[] groups) {
        if (connection == null) {
            return false;
        }
        try {
            jidString = jidString + "@" + XMPP_SERVICE_DONAIN;
            BareJid bareJid = JidCreate.from(jidString).asBareJid();
            if (TextUtils.isEmpty(again)) {
                again = jidString.substring(0, jidString.indexOf("@"));
            }
            Roster.getInstanceFor(connection).createEntry(bareJid, again, groups);
            return true;
        } catch (XmppStringprepException | InterruptedException | SmackException.NotLoggedInException | XMPPException.XMPPErrorException | SmackException.NotConnectedException | SmackException.NoResponseException e) {
            e.printStackTrace();
            LogUtils.e("异常报告：" + e.getMessage());
        }
        return false;
    }

    /**
     * 订阅
     *
     * @param jidString 用户jid
     * @param type      订阅类型
     */
    public boolean subscribed(String jidString, Presence.Type type) {
        if (connection != null) try {
            Presence presence = new Presence(type);
            presence.setTo(JidCreate.from(jidString + "@" + XMPP_SERVICE_DONAIN));
            connection.sendStanza(presence);
            return true;
        } catch (XmppStringprepException | SmackException.NotConnectedException | InterruptedException e) {
            e.printStackTrace();
        }
        return false;
    }

    public void dd() {

        if (connection == null) {
            return;
        }
        String roomName = "chat_root@conference." + connection.getXMPPServiceDomain().toString();
        MultiUserChatManager manager = MultiUserChatManager.getInstanceFor(connection);
        try {
            List<EntityBareJid> lists = manager.getJoinedRooms(connection.getUser().asEntityJidIfPossible());
            LogUtils.e("---" + lists.size());
            for (EntityBareJid jid : lists) {
                LogUtils.e("-----" + jid.asEntityBareJidString());
            }
            RoomInfo info = manager.getRoomInfo(JidCreate.entityBareFrom(roomName));
            LogUtils.e("-ddd--" + info.getOccupantsCount());
        } catch (SmackException.NoResponseException e) {
            e.printStackTrace();
        } catch (XMPPException.XMPPErrorException e) {
            e.printStackTrace();
        } catch (SmackException.NotConnectedException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (XmppStringprepException e) {
            e.printStackTrace();
        }
    }

    /**
     * 创建聊天室
     */
    public void createChatRoom(String roomName, String nickName) {
        if (connection == null) {
            return;
        }
        roomName = roomName + "@conference." + connection.getXMPPServiceDomain().toString();
        try {

            MultiUserChatManager manager = MultiUserChatManager.getInstanceFor(connection);
            MultiUserChat muc = manager.getMultiUserChat(JidCreate.entityBareFrom(roomName));
            //创建并加入
            muc.createOrJoin(Resourcepart.from(nickName));
            muc.grantMembership(JidCreate.from("lemlin@101.37.253.11"));
            // 获得聊天室的配置表单
            Form form = muc.getConfigurationForm();
            // 根据原始表单创建一个要提交的新表单。
            Form submitForm = form.createAnswerForm();
            // 向要提交的表单添加默认答复
            for (FormField field : form.getFields()) {
                LogUtils.e(JsonUtils.objectToString(field));
                if (field.getVariable() != null && field.getType() != FormField.Type.hidden)
                    submitForm.setDefaultAnswer(field.getVariable());
            }
            List<String> owners = new ArrayList<>();
            owners.add("linlimin@101.37.253.11");
            //设置聊天室的新拥有者
            submitForm.setAnswer("muc#roomconfig_roomowners", owners);
//            submitForm.setAnswer("muc#roomconfig_roommembers", owners);
            // 设置聊天室是持久聊天室，即将要被保存下来
            submitForm.setAnswer("muc#roomconfig_persistentroom", true);
            // 房间仅对成员开放
            submitForm.setAnswer("muc#roomconfig_membersonly", true);
            // 允许占有者邀请其他人
            submitForm.setAnswer("muc#roomconfig_allowinvites", true);
            // 进入是否需要密码
            submitForm.setAnswer("muc#roomconfig_passwordprotectedroom", false);
            // 能够发现占有者真实 JID 的角色
            // submitForm.setAnswer("muc#roomconfig_whois", "anyone");
            // 记录房间聊天
            submitForm.setAnswer("muc#roomconfig_enablelogging", true);
            // 仅允许注册的昵称登录
            submitForm.setAnswer("x-muc#roomconfig_reservednick", true);
            // 允许使用者修改昵称
            submitForm.setAnswer("x-muc#roomconfig_canchangenick", true);
            // 允许用户注册房间
            submitForm.setAnswer("x-muc#roomconfig_registration", true);
            // 发送已完成的表单（有默认值）到服务器来配置聊天室
            muc.sendConfigurationForm(submitForm);
            muc.addMessageListener(new MessageListener() {
                @Override
                public void processMessage(Message message) {
                    LogUtils.e("-----------" + message.getBody());
                }
            });
            RoomInfo roomInfo = manager.getRoomInfo(JidCreate.entityBareFrom(roomName));
            LogUtils.e("创建成功" + roomInfo.getSubject());

        } catch (XmppStringprepException | MultiUserChatException.MucAlreadyJoinedException | XMPPException.XMPPErrorException | SmackException.NotConnectedException | SmackException.NoResponseException | MultiUserChatException.NotAMucServiceException | InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     *
     */
    public void getJoinedRooms() {
        // Get the MultiUserChatManager
        MultiUserChatManager manager = MultiUserChatManager.getInstanceFor(connection);
        Set<EntityBareJid> joinedRooms = manager.getJoinedRooms();
        LogUtils.e(JsonUtils.objectToString(joinedRooms));
    }

    /**
     * 加入聊天室
     */
    public void joinChatRoom(String roomName, String nickName) {

        if (connection == null) {
            return;
        }
        roomName = roomName + "@conference." + connection.getXMPPServiceDomain().toString();
        try {
            MultiUserChat muc = MultiUserChatManager.getInstanceFor(connection)
                    .getMultiUserChat(JidCreate.entityBareFrom(roomName));
            muc.join(Resourcepart.from(nickName));
        } catch (XmppStringprepException | XMPPException.XMPPErrorException | SmackException.NotConnectedException | SmackException.NoResponseException | MultiUserChatException.NotAMucServiceException | InterruptedException e) {
            e.printStackTrace();
        }
    }

    /**
     * 搜索用户
     *
     * @param search 搜索内容
     */
    public List<ReportedData.Row> userSearch(String search) throws SmackException.NoResponseException, XMPPException.XMPPErrorException, SmackException.NotConnectedException, InterruptedException, XmppStringprepException {
        UserSearchManager searchManager = new UserSearchManager(connection);
        DomainBareJid jid = JidCreate.domainBareFrom(("search." + XMPP_SERVICE_DONAIN));
        Form form = searchManager.getSearchForm(jid);
        Form submitForm = form.createAnswerForm();
        submitForm.setAnswer(("Username"), (true));
        submitForm.setAnswer(("search"), search);
        return searchManager.getSearchResults(submitForm, jid).getRows();
    }

    /*------------------------------------连接监听----------------------------------------------*/

    /**
     * 连接成功
     */
    @Override
    public void connected(XMPPConnection connection) {
        LogUtils.e("连接成功");
    }

    /**
     * 认证成功
     */
    @Override
    public void authenticated(XMPPConnection connection, boolean resumed) {
        LogUtils.e("认证成功");
    }

    /**
     * 关闭连接
     */
    @Override
    public void connectionClosed() {
        LogUtils.e("关闭连接");
    }

    /**
     * 连接异常
     */
    @Override
    public void connectionClosedOnError(Exception e) {
        LogUtils.e("连接异常：" + e.getMessage());
        connection.disconnect();
    }

    /*------------------------------------用户状态监听----------------------------------------------*/


    public RosterEntry getEntrie(String jid) {
        if (connection == null)
            return null;
        try {
            return Roster.getInstanceFor(connection).getEntry(JidCreate.from(jid).asBareJid());
        } catch (XmppStringprepException e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public void processStanza(Stanza packet) {
        if (packet instanceof Presence) {
            Presence presence = (Presence) packet;
            String from = presence.getFrom().asBareJid().toString();
            String to = presence.getTo().asBareJid().toString();
            StringBuilder sb = new StringBuilder();
            switch (presence.getType()) {
                case subscribe:
                    FriendGood friendGood = new FriendGood();
                    friendGood.setJid(from);
                    friendGood.setName(from.substring(0, from.indexOf("@")));
                    RosterEntry entry = getEntrie(from);
                    if (entry != null && entry.getType() == RosterPacket.ItemType.to) {
                        subscribed(from.substring(0, from.indexOf("@")), Presence.Type.subscribed);
                        friendGood.setSub("both");
                    } else {
                        friendGood.setSub("none");
                    }
                    FriendGood friend = APPIM.getDaoSession().getFriendGoodDao().queryBuilder()
                            .where(FriendGoodDao.Properties.Name.eq(from.substring(0, from.indexOf("@")))).unique();
                    if (friend == null) {
                        APPIM.getDaoSession().getFriendGoodDao().insert(friendGood);
                        EventBus.getDefault().post(friendGood);
                    }
                    sb.append("请求添加为好友");
                    break;
                case subscribed:
                    sb.append("同意订阅");
                    break;
                case unsubscribe:
                    sb.append("取消订阅");
                    break;
                case unsubscribed:
                    sb.append("拒绝订阅");
                    break;
                case unavailable:
                    String userName =
                            APPIM.getLoginUser().asBareJid().getLocalpartOrNull().intern();
                    if (from.equals(userName))
                        setPresence(1);
                    sb.append("离线");
                    break;
                case available:
                    sb.append("上线");
                    break;
            }
            LogUtils.e(sb.append("，from：").append(from).append("，to：").append(to).toString());

        }
    }

    /*------------------------------------消息发送接收监听----------------------------------------------*/

    /**
     * 消息发送监听
     */
    @Override
    public void newOutgoingMessage(EntityBareJid to, Message message, Chat chat) {
        LogUtils.e("发送聊天消息：" + JsonUtils.objectToString(message));
        message.setFrom(connection.getUser());
        this.setMessage(to, message);
    }

    /**
     * 消息接收监听
     */
    @Override
    public void newIncomingMessage(EntityBareJid from, Message message, Chat chat) {
        LogUtils.e("接收聊天消息：" + JsonUtils.objectToString(message));

        Vibrator vibrator = (Vibrator) APPIM.getContext().getSystemService(Service.VIBRATOR_SERVICE);
        vibrator.vibrate(200);
        this.setMessage(from, message);
    }

    private void setMessage(EntityBareJid name, Message message) {
        String userName = name.asBareJid().getLocalpartOrNull().intern();
        long msgTime = 0;
        if (message.getExtension(("urn:xmpp:delay")) == null) {
            Date date = new Date(System.currentTimeMillis());
            msgTime = date.getTime();
        } else {
            String stamp = JsonUtils.objectToString(message.getExtension(("urn:xmpp:delay")));
            SimpleDateFormat sdfAug = new SimpleDateFormat(("MMM dd, yyyy HH:mm:ss"), Locale.US);
            try {
                Date date = sdfAug.parse(JsonUtils.stringToMap(stamp).get("stamp").toString());
                msgTime = date.getTime();
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        ChatRecord chatRecord = new ChatRecord();
        chatRecord.setName(userName);
        chatRecord.setLastMsgText(message.getBody());
        chatRecord.setLastMsgTime(msgTime);
        chatRecord.setLastMsgType("TEXT");
        if (!message.getFrom().asBareJid().toString().equals(APPIM.getLoginUser().asBareJid().toString())) {
            chatRecord.setLastMsgCount(1);
        } else {
            chatRecord.setLastMsgCount(0);
        }
        ChatRecordDao recordDao = APPIM.getDaoSession().getChatRecordDao();
        QueryBuilder<ChatRecord> builder = recordDao.queryBuilder()
                .where(ChatRecordDao.Properties.Name.eq(userName));
        if (builder.unique() == null) {
            recordDao.insert(chatRecord);
        } else {
            chatRecord.setId(builder.unique().getId());
            if (!message.getFrom().asBareJid().toString().equals(APPIM.getLoginUser().asBareJid().toString())) {
                chatRecord.setLastMsgCount((builder.unique().getLastMsgCount() + 1));
            }
            recordDao.update(chatRecord);
        }
        ChatMessage msg = new ChatMessage();
        msg.setName(userName);
        msg.setFrom(message.getFrom().asBareJid().getLocalpartOrNull().intern());
        msg.setTo(message.getTo().asBareJid().getLocalpartOrNull().intern());
        msg.setMsgText(message.getBody());
        msg.setMsgType("TEXT");
        msg.setMsgTime(msgTime);
        msg.setMsgFlag(false);
        APPIM.getDaoSession().getChatMessageDao().insert(msg);
        EventBus.getDefault().post(msg);
    }

    /*------------------------------------PING监听----------------------------------------------*/

    /**
     * 服务器ping失败时调用
     */
    @Override
    public void pingFailed() {

        LogUtils.e("服务器PING失败" + connection.isConnected() + "," + connection.isAuthenticated());
        if (connection == null) {
            return;
        }
        connection.disconnect();
    }

    /**
     * 定时发送心跳包任务
     */
    class PingMyServerTimerTask extends TimerTask {

        PingManager pingManager;

        PingMyServerTimerTask(PingManager pingManager) {
            this.pingManager = pingManager;
        }

        @Override
        public void run() {
            try {
                LogUtils.e("------------------开始PING-------------------");
                String str = "客户端向服务端发送心跳包：";
                boolean isPingMyServer = pingManager.pingMyServer((false), TIME_DELAY);
                if (isPingMyServer) {
                    LogUtils.e(str + "PING【成功】");
                } else {
                    LogUtils.e(str + "PING【失败】");
                    int i = 0;
                    while (i < 2) {
                        Thread.sleep(TIME_DELAY);
                        isPingMyServer = pingManager.pingMyServer((false), TIME_DELAY);
                        if (isPingMyServer) {
                            LogUtils.e(str + "重新尝试PING【成功】");
                            break;
                        } else {
                            LogUtils.e(str + "重新尝试PING【失败】");
                        }
                        i++;
                    }
                    if (!isPingMyServer) {
                        Thread.sleep(TIME_DELAY);
                        isPingMyServer = pingManager.pingMyServer((true), TIME_DELAY);
                        if (isPingMyServer) {
                            LogUtils.e(str + "重新尝试PING【成功】");
                        } else {
                            LogUtils.e(str + "重新尝试PING【失败】");
                        }
                    }

                }
            } catch (SmackException.NotConnectedException | InterruptedException e) {
                e.printStackTrace();
                mTimer.cancel();
            }
        }
    }
}
